/*!
 * Node-attribute module v1.0.0 of jRaiser javascript library
 * http://code.google.com/p/jraiser/
 *
 * Author: Heero.Luo
 * Licensed under MIT license
 *
 * Date: Tue Jun 05 2012 10:35:34 GMT+0800
 */
define(function(require, exports, module) { 'use strict';

var core = require('core/1.0.x/core'), $base = require('node-base/1.0.x/node-base');


/**
 * 属性访问
 */

// 特殊属性名映射
var attrMap = !document.documentElement.hasAttribute ? {
	'for' : 'htmlFor',
	'class' : 'className'
} : {
	'htmlFor' : 'for',
	'className' : 'class'
};

// 特殊属性获取
var attrHooks = { };
if ('cssText' in document.documentElement.style) {
	attrHooks.style = {
		get : function(node) { return node.style.cssText.toLowerCase(); },
		set : function(node, val) { node.style.cssText = val;	}
	};
}

// 修复属性名
function fixAttrName(node, name) {
	if (!$base.isXMLNode(node)) { name = name.toLowerCase(); }
	return attrMap[name] || name;
}

/**
 * 获取节点属性值
 * @param {DOMElement} 节点
 * @param {String} 属性名
 * @return {String} 属性值
 */
function getAttr(node, name) {
	var trueName = fixAttrName(node, name), result = (attrHooks[trueName] || 0).get;
	if (result) {
		return result(node);
	} else {
		result = node.getAttribute(trueName);
		return typeof result === 'boolean' ? (result ? name.toLowerCase() : '') : result;
	}
}
/**
 * 设置节点属性值
 * @param {DOMElement} 节点
 * @param {String} 属性名
 * @param {String} 属性值
 */
function setAttr(node, name, val) {
	var trueName = fixAttrName(node, name), hook = (attrHooks[trueName] || 0).set;
	if (hook) {
		return hook(node, val);
	} else {
		var isRemove;
		if (typeof val === 'boolean') {
			setProp(node, name, val);
			if (val) {
				name = name.toLowerCase();
			} else {
				isRemove = true;
			}
		}
		
		if (isRemove) {
			removeAttr(node, [name], true);
		} else {
			node.setAttribute(fixAttrName(node, name), val);
		}
	}
}
/**
 * 移除节点属性
 * @param {DOMElement} 节点
 * @param {String|Array<String>} 属性名。多个属性名用空格隔开，或者以数组传入
 * @param {Boolean} 此参数主要用于循环调用时，忽略对属性名的重复解析
 */
function removeAttr(node, names, isPass) {
	if (!isPass) { names = $base.splitBySpace(names); }

	names.forEach(function(name) {
		node.removeAttribute(fixPropName(node, name));
	});
}


/**
 * 特性访问
 */

// 特性映射
var propMap = {
	'tabindex' : 'tabIndex',
	'readonly' : 'readOnly',
	'maxlength' : 'maxLength',
	'cellspacing' : 'cellSpacing',
	'cellpadding' : 'cellPadding',
	'rowspan' : 'rowSpan',
	'colspan' : 'colSpan',
	'usemap' : 'useMap',
	'frameborder' : 'frameBorder',
	'contenteditable' : 'contentEditable'
};
core.extend(propMap, attrMap);

// 是否支持特性访问
function isSupportProp(node) { return !$base.isXMLNode(node) && node.nodeType === 1; }

// 修复特性名
function fixPropName(node, name) {
	if (!$base.isXMLNode(node)) { name = name.toLowerCase(); }
	return propMap[name] || name;
}

/**
 * 获取节点特性值
 * @param {DOMElement} 节点
 * @param {String} 特性名
 * @return {String} 特性值
 */
function getProp(node, name) {
	return isSupportProp(node) ? node[fixPropName(node, name)] : null;
}
/**
 * 设置节点特性值
 * @param {DOMElement} 节点
 * @param {String} 特性名
 * @param {String} 特性值
 */
function setProp(node, name, val) {
	if (isSupportProp(node)) { node[fixPropName(node, name)] = val; }
}
/**
 * 移除节点特性
 * @param {DOMElement} 节点
 * @param {String|Array<String>} 特性名。多个特性名用空格隔开，或者以数组传入
 * @param {Boolean} 此参数主要用于循环调用时，忽略对特性名的重复解析
 */
function removeProp(node, names, isPass) {
	if (!isPass) { names = $base.splitBySpace(names); }
	
	names.forEach(function(name) {
		name = fixPropName(node, name);
		try {
			delete node[name];
		} catch(e) { }
	});
}


/**
 * 节点文本内容访问
 */
 
/**
 * 获取节点文本内容
 * @param {DOMElement} 节点
 * @return {String} 文本内容
 */
var getText
/**
 * 设置节点文本内容
 * @param {DOMElement} 节点
 * @param {String} 新文本内容
 */
var setText;

if ('textContent' in document.documentElement) {
	getText = function(node) { return node.textContent; };
	setText = function(node, content) { node.textContent = content; };
} else {
	getText = function(node) { return node.innerText || node.nodeValue; };
	setText = function(node, content) {
		if ('innerText' in node) {
			node.innerText = content;
		} else if ('nodeValue' in node) {
			node.nodeValue = content;
		}
	};
}


core.extend(exports, {
	/**
	 * See line 43
	 */
	getAttr : getAttr,
	
	/**
	 * See line 58
	 */
	setAttr : setAttr,
	
	/**
	 * See line 86
	 */
	removeAttr : removeAttr,
	
	/**
	 * See line 129
	 */
	getProp : getProp,
	
	/**
	 * See line 138
	 */
	setProp : setProp,
	
	/**
	 * See line 147
	 */
	removeProp : removeProp,
	
	/**
	 * See line 169
	 */
	getText : getText,
	
	/**
	 * See line 175
	 */
	setText : setText,
	
	/**
	 * node模块的扩展接口
	 */
	nodeApis : {
		/**
		 * 获取当前节点集合中第一个节点的属性值
		 * @param {String} 属性名
		 * @return {String} 属性值
		 */
		/**
		 * 设置当前所有节点的属性值
		 * @param {String|Object} 属性名或包含属性名值的对象
		 * @param {String} 属性值
		 * @return {NodeList} 当前节点集合
		 */
		attr : function(name, val) {
			return core.access(this, name, val, true, {
				get : getAttr,
				set : setAttr
			});
		},
		
		/**
		 * 移除当前所有节点的指定属性
		 * @param {String|Array<String>} 属性名。多个属性名用空格隔开，或者以数组传入
		 * @return {NodeList} 当前节点集合
		 */
		removeAttr : function(names) {
			names = $base.splitBySpace(names);
			
			this.forEach(function(elt) {
				removeAttr(elt, names);
			});
			return this;
		},
		
		/**
		 * 获取当前节点集合中第一个节点的特性值
		 * @param {String} 特性名
		 * @return {String} 特性值
		 */
		/**
		 * 设置当前所有节点的特性值
		 * @param {String|Object} 特性名或包含特性名值的对象
		 * @param {String} 特性值
		 * @return {NodeList} 当前节点集合
		 */
		prop : function(name, val) {
			return core.access(this, name, val, true, {
				get : getProp,
				set : setProp
			});
		},
		
		/**
		 * 移除当前所有节点的指定特性
		 * @param {String|Array<String>} 特性名。多个特性名用空格隔开，或者以数组传入
		 * @return {NodeList} 当前节点集合
		 */
		removeProp : function(names) {
			names = $base.splitBySpace(names);
			
			this.forEach(function(elt) {
				removeProp(elt, names);
			});
			return this;
		},
		
		/**
		 * 获取当前节点集合中第一个节点的文本内容
		 * @return {String} 文本内容
		 */
		/**
		 * 设置当前所有节点的文本内容
		 * @param {String|Function} 新文本内容
		 * @return {NodeList} 当前节点集合
		 */
		text : function(content) {
			return core.access(this, null, content, true, {
				get : getText,
				set : function(node, k, v) { setText(node, v); }
			});
		},
		
		/**
		 * 获取当前节点集合中第一个节点inner html
		 * @return {String} inner html
		 */
		/**
		 * 设置当前所有节点的inner html
		 * @param {String|Function} 新inner html
		 * @return {NodeList} 当前节点集合
		 */
		html : function(content) {
			return core.access(this, null, content, true, {
				get : function(node, k) { return node.innerHTML; },
				set : function(node, k, v) { node.innerHTML = v; }
			});
		},
		
		/**
		 * 获取当前节点集合中第一个节点的value属性值
		 * @return {String} value属性值
		 */
		/**
		 * 设置当前所有节点的value属性值
		 * @param {String|Function} 新value属性值
		 * @return {NodeList} 当前节点集合
		 */
		val : function(val) {
			return core.access(this, null, val, true, {
				get : function(node, k) { return node.value; },
				set : function(node, k, v) { node.value = v; }
			});
		}
	}
});

});